import { Scene } from "@/utils/render2/scene";
import { Sprite } from "@/utils/render2/sprite";

interface TRaffleVWheelConfig {
  imgTurntable: string; // 转盘图
  imgTurntableBorder: string; // 转盘边框
  imgDividing: string; // 分割线图
  listGifts: string[]; // 奖品列表
  numGiftScale: number; // 奖品的缩放比例 0 - 1
  numRadius: number; // 调整奖品到圆心的距离
}

const innerConfig: TRaffleVWheelConfig = {
  imgTurntable: require('@/assets/imgs/roundabout/rotatePan.png'),
  imgTurntableBorder: require('@/assets/imgs/roundabout/rotateBorder.png'),
  imgDividing: require('@/assets/imgs/roundabout/device.png'), 
  listGifts: [
    require('@/assets/imgs/roundabout/award5.png'),
    require('@/assets/imgs/roundabout/award4.png'),
    require('@/assets/imgs/roundabout/award3.png'),
    require('@/assets/imgs/roundabout/award2.png'),
    require('@/assets/imgs/roundabout/award1.png'),
    require('@/assets/imgs/roundabout/award0.png'),
  ],
  numGiftScale: 0.8,
  numRadius: 160,
}

class RoundAbout {
  private scene!: Scene;
  private lastAngle = 0; // 上一把走过的角度
  private opening = false; // 开奖中
  public got = false // 开奖

  public set = {
    awardedIndex: 5
  }

  constructor (
    private parent: Element,
    private canvas: HTMLCanvasElement,
    immediate: boolean = false
  ) {
    if (immediate) {
      this.initCanvas();
    }
  }

  private get awardedIndex () {
    return this.set.awardedIndex || 0
  }

  // 加载奖品
  private addGifts() {
    const sources: any = {};
    innerConfig.listGifts.forEach((item, index) => {
      sources[`award${index}`] = item;
    });
    return sources;
  }

  // 加载资源
  private async loadSources() {
    const sources = {
      turntable: innerConfig.imgTurntable,
      turntableBorder: innerConfig.imgTurntableBorder,
      diving: innerConfig.imgDividing
    };
    const gifts = this.addGifts();
    await this.scene.load({
      ...gifts,
      ...sources,
    });
  }

  async initCanvas () {
    this.scene = new Scene(this.parent, this.canvas);
    await this.loadSources();
    this.drawTurntable();
    this.drawAwards();
  }

  //* <- 渲染
  // 绘制分割线
  private drawDiving(angle: number) {
    const divingTexture = this.scene.getTextures('diving');
    const diving = new Sprite({
      texture: divingTexture,
      width: divingTexture.width,
      height: this.scene.height / 2,
      pos: [this.scene.width / 2, this.scene.height / 2],
      angle,
      anchor: [0.5, 1]
    });
    this.scene.addChild(diving);
  }

  // 绘制转盘
  private drawTurntable () {
    const turntableTexture = this.scene.getTextures('turntable');
    const turntableBorderTexture = this.scene.getTextures('turntableBorder');
    const turntable = new Sprite({
      texture: turntableTexture,
      width: this.scene.width,
      height: this.scene.height,
    });
    const turntableBorder = new Sprite({
      texture: turntableBorderTexture,
      width: this.scene.width,
      height: this.scene.height,
    });
    // 绘制转盘背景
    this.scene.addChild(turntable);
    // 绘制分割线
    for (let i = 0; i < innerConfig.listGifts.length; i++) {
      const angle = 360 / innerConfig.listGifts.length;
      this.drawDiving(angle * i);
    }
    // 绘制转盘边框
    this.scene.addChild(turntableBorder);
  }

  /** 绘制奖品 */
  private drawAwards () {
    const awards: string[] = [];
    for (let i = 0; i < innerConfig.listGifts.length; i++) {
      awards.push(`award${i}`);
    }
    // 计算渲染尺寸和实际尺寸的比例
    const scale = this.scene.width / this.scene.getTextures('turntable').width;
    // 遍历奖品
    for (let i = 0; i < innerConfig.listGifts.length; i++) {
      const circleCenter = [this.scene.width / 2, this.scene.height / 2]; // 圆心
      const average = 360 / innerConfig.listGifts.length; // 平均角度
      const radius = innerConfig.numRadius || 0; // 奖品所在圆的半径
      const awardTexture = this.scene.getTextures(awards[i]); // 纹理
      if (!awardTexture) return;
      const startAngle = 180 + average / 2; // 第一个奖品所在的角度
      let angle = startAngle + average * i; // 顺时针递减角度
      // 根据公式, 计算坐标
      let x = circleCenter[0] + Math.sin(2 * Math.PI / 360 * angle) * (radius * scale);
      let y = circleCenter[1] + Math.cos(2 * Math.PI / 360 * angle) * (radius * scale);
      // 计算元素渲染的尺寸
      let singleLong = (Math.PI * radius * 2 / innerConfig.listGifts.length); // 单个扇形的周长
      singleLong = singleLong * (innerConfig.numGiftScale || 1);
      let spScale = singleLong / awardTexture.width;
      const spWidth = Math.floor(singleLong * scale);
      const spHeight = Math.floor(awardTexture.height * spScale * scale);
      // 渲染元素
      const sp = new Sprite({
        texture: awardTexture,
        width: spWidth,
        height: spHeight,
        pos: [x, y],
        anchor: [0.5, 0.5],
        angle: 180 - angle
      });
      this.scene.addChild(sp);
    }
  }
  //* ->

  // 旋转动画
  private rotateAnimation() {
    const minRotateRounds = 10; // 最少旋转圈数量
    let runCount = 1; // 计数器
    let angle = 360 / innerConfig.listGifts.length; // 平均角度
    let awardCount = 0; // 开奖计数器
    let awardIdx = 0; // 奖品索引, 默认为0
    // 设置动画过渡时间
    this.canvas.style.transition = 'all 10s';
    // 开奖动画, 将动画旋转到对应奖品
    const awardRun = () => {
      const rotate = angle * runCount + this.lastAngle;
      this.canvas.style.transform = `rotate(${rotate}deg)`;
      if (awardCount < awardIdx) {
        awardCount++;
        runCount++;
        requestAnimationFrame(awardRun);
      } else {
        console.log('awardIdx', awardIdx);
        //* <- 在转盘多转或者少转时（由于浏览器设备原因导致的 requestAnimationFrame 执行不及时导致的），进行调整
        const awardPosAngle = angle * awardIdx // 正常奖品所在角度
        const roundTotalInteger = Math.floor(rotate / 360) // 算出总共完整走了多少圈
        const angleToalInteger = roundTotalInteger * 360 // 算出总共完整走了多少度
        const dif = rotate - (angleToalInteger + awardPosAngle) // 计算实际与理论的差，得出来的结果就是多走的度
        // 再走一圈，减去多出来的度数
        const againRound = 360 - dif
        const lastRound = againRound + rotate
        //* ->

        // 将指针移到奖品所在栏的中间附近，即需要再多一个平均角度，并让其随机
        let pointRandom = Math.min(
          Math.floor(Math.random() * angle) + angle * 0.1,
          angle * 0.85
        ); // 在一个平均角度中, 随机获得指针最后停摆的位置数值
        pointRandom = Math.floor(pointRandom);
        const all = lastRound + pointRandom; // 当前走过的总角度
        this.canvas.style.transform = `rotate(${all}deg)`;
        this.lastAngle = awardPosAngle + pointRandom
      }
    };

    // 旋转动画
    const run = () => {
      const rotate = angle * runCount + this.lastAngle;
      this.canvas.style.transform = `rotate(${rotate}deg)`;
      // 达标条件, 获取奖品索引, 执行最后的动画
      if (runCount >= minRotateRounds * innerConfig.listGifts.length && this.got) {
        awardIdx = this.awardedIndex
        awardRun();
        return;
      }
      runCount++;
      requestAnimationFrame(run);
    };
    requestAnimationFrame(run);
  }

  // 悄咪咪地把旋转的角度设置为一圈旋转的角度
  private async silentToOneRound(angle: number) {
    this.canvas.style.transition = 'all 0s';
    this.canvas.style.transform = `rotate(${angle}deg)`;
    return new Promise((resolve) => {
      setTimeout(() => {
        this.canvas.style.transition = '';
        resolve(true);
      }, 50);
    });
  }

  public start () {
    if (this.opening) return
    this.opening = true;
    this.rotateAnimation();
  }

  public end () {
    this.opening = false;
    this.got = false;
    this.silentToOneRound(this.lastAngle);
  }

  public open () {
    this.got = true
  }
}

export {
  RoundAbout
}